package com.comp6231.client;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.sql.Date;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.omg.CORBA.ORB;

import com.comp6231.DPIS.StationServer;
import com.comp6231.DPIS.StationServerHelper;
import com.comp6231.common.Log;
import com.comp6231.common.LogOperationException;
import com.comp6231.common.Stations;

/**
 * 
 * This is the DPIS client system's main class This class verify police offices
 * badge numbers and then connect to servers and provide options to perform
 * operations allowed by server
 * 
 * @author sknarula (narula.sk@gmail.com)
 * @since September 2013
 * 
 * 
 */
public class OfficerClient {

	/**
	 * Class attributes to hold the badge number of the office using the system
	 * currently and the server reference
	 */
	static String badgeId = null;
	static String stationName = null;
	static Scanner keyboard = new Scanner(System.in);

	/**
	 * Declare the server
	 */
	StationServer server = null;
	// save the reference to avoid unnecessary I/O
	String feIOR = null;

	/**
	 * Constructor to lookup the server object based on station name provided
	 * 
	 * @param stationName
	 * @throws RemoteException
	 * @throws NotBoundException
	 * @throws MalformedURLException
	 */
	public OfficerClient(String[] args, String stationName) throws IOException {

		ORB orb = ORB.init(args, null);

		// check if the ior is saved (it is saved upon using it once)
		String ior = feIOR;
		if (ior == null) {
			// accessing the server first time, so get it from file
			BufferedReader br = new BufferedReader(new FileReader(
					System.getProperty("user.dir")
							+ "/src/com/comp6231/frontend/" + "FEIor.txt"));
			ior = br.readLine();
			br.close();
			feIOR = ior;
		}

		org.omg.CORBA.Object o = orb.string_to_object(ior);

		server = StationServerHelper.narrow(o);
	}

	/**
	 * Main method to start the client thread
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		int length = args.length;
		for (int i = 0; i < length; i++) {
			System.out.println(args[i]);
		}

		System.out.println("\nOfficer Client System started...Welcome\n");
		// get the badge id from user and set the badge id and station name
		getAndVerifyBadgeId();

		try {
			OfficerClient client = new OfficerClient(args, stationName);
			client.run();
		} catch (IOException e) {
			System.out
					.println("Officer Client could not connect to the server.");
			e.printStackTrace();
		}
	}

	/**
	 * Start the thread, display menu and perform tasks based on user input
	 */
	public void run() {
		char userInput;
		do {
			displayMenu();
			String stringInput = keyboard.nextLine();
			userInput = stringInput.charAt(0);

			try {
				String firstName = "";
				String lastName = "";
				String status = "";
				String recordId = "";
				boolean success = false;
				Log log = null;

				switch (userInput) {
				case '1': // create criminal record
					String crimeDesc = "";

					System.out.println("Criminal first name: ");
					firstName = keyboard.nextLine();
					System.out.println("Criminal last name: ");
					lastName = keyboard.nextLine();
					System.out.println("Crime description: ");
					crimeDesc = keyboard.nextLine();
					System.out.println("Criminal Status (captured/otr): ");
					status = keyboard.nextLine().toUpperCase();

					success = server.createCRecord(badgeId, firstName,
							lastName, crimeDesc, status);

					// log the creation of the record
					log = new Log(
							System.getProperty("user.dir")
									+ "/src/com/comp6231/client/logs/"
									+ badgeId + ".txt",
							"Requested Creation of Criminal Record",
							badgeId,
							(success ? "Operation Successful"
									: "Operation Failed: See server log for details"));
					log.save();

					System.out.println("\n");
					break;

				case '2': // create missing record
					String address = "";
					String missingFrom = "";
					String missingSince = "";

					System.out.println("Missing person's first name: ");
					firstName = keyboard.nextLine();
					System.out.println("Missing person's last name: ");
					lastName = keyboard.nextLine();
					System.out.println("Missing person's address: ");
					address = keyboard.nextLine();
					System.out.println("Missing since (yyyy-mm-dd): ");
					missingSince = keyboard.nextLine();
					System.out.println("Missing from: ");
					missingFrom = keyboard.nextLine();
					System.out.println("Missing Status (missing/found): ");
					status = keyboard.nextLine().toUpperCase();

					// this is just a check now, although I am sending date as a
					// string to server
					try {
						Date.valueOf(missingSince);
					} catch (IllegalArgumentException e) {
						System.out
								.println("\nInvalid Date is entered, can't create record at this moment");
						break;
					}

					success = server.createMRecord(badgeId, firstName,
							lastName, address, missingSince, missingFrom,
							status);

					// log the creation of the record
					log = new Log(
							System.getProperty("user.dir")
									+ "/src/com/comp6231/client/logs/"
									+ badgeId + ".txt",
							"Requested Creation of Missing Record",
							badgeId,
							(success ? "Operation Successful"
									: "Operation Failed: See server log for details"));
					log.save();

					System.out.println("\n");
					break;

				case '3': // edit a record
					String newStatus = "";

					System.out.println("Last name in record: ");
					lastName = keyboard.nextLine();
					System.out.println("Record id to modify: ");
					recordId = keyboard.nextLine();
					System.out.println("New Status: ");
					newStatus = keyboard.nextLine().toUpperCase();

					success = server.editRecord(badgeId, lastName, recordId,
							newStatus);

					// log the creation of the record
					log = new Log(
							System.getProperty("user.dir")
									+ "/src/com/comp6231/client/logs/"
									+ badgeId + ".txt",
							"Requested Editing of Record",
							badgeId,
							(success ? "Operation Successful"
									: "Operation Failed: See server log for details"));
					log.save();

					System.out.println("\n");
					break;

				case '4': // get record count
					String countReturned = server.getRecordCounts(badgeId);
					System.out.println(countReturned);

					// log the creation of the record
					log = new Log(System.getProperty("user.dir")
							+ "/src/com/comp6231/client/logs/" + badgeId
							+ ".txt", "Requested Record Count", badgeId,
							"Count Returned: \"" + countReturned + "\"");
					log.save();

					System.out.println("\n");
					break;

				case '5': // transfer a record
					String newStationServerName = "";

					System.out.println("Record id to tranfer: ");
					recordId = keyboard.nextLine();
					System.out
							.println("Name of the remote server to tranfer to: ");
					newStationServerName = keyboard.nextLine();

					success = server.transferRecord(badgeId, recordId,
							newStationServerName.toUpperCase());

					// log the creation of the record
					log = new Log(
							System.getProperty("user.dir")
									+ "/src/com/comp6231/client/logs/"
									+ badgeId + ".txt",
							"Requested transfer of Record",
							badgeId,
							(success ? "Operation Successful"
									: "Operation Failed: See server log for details"));
					log.save();

					System.out.println("\n");
					break;

				}
			} catch (LogOperationException e) {
				System.out.println(e.getMessage());
				System.out.println("\n");
			}
		} while (userInput != 'q' && userInput != 'Q');
	}

	/**
	 * Method to display the menu
	 */
	private void displayMenu() {
		System.out.println("\nOptions: ");
		System.out.println("1:	Create Criminal Record");
		System.out.println("2:	Create Missing Record");
		System.out.println("3:	Edit a Record");
		System.out.println("4:	Get Record Count");
		System.out.println("5:	Transfer Record");
		System.out.println("6:	Print Hashtable to File");
		System.out.println("q:	Quit");

		System.out.println("\nPlease enter your choice.");
	}

	/**
	 * method to get police officer badge number and verify it to ensure its a
	 * valid
	 */
	private static void getAndVerifyBadgeId() {
		// input the badge id
		String userInput = null;
		System.out.println("\nPlease enter you Badge Id to log on: ");
		userInput = keyboard.nextLine();

		// verify and save the badge id
		Pattern pattern = Pattern.compile("\\d+");
		Matcher matcher = pattern.matcher(userInput);
		String tempStationName = "";
		try {
			matcher.find();
			tempStationName = userInput.substring(0,
					userInput.indexOf(matcher.group())).toUpperCase();
			stationName = Stations.getEnumValue(tempStationName)
					.getPoliceStationType();

			badgeId = userInput;
			System.out.println("Welcome officer " + badgeId
					+ ", you will be now connected to station " + stationName);

		} catch (IllegalArgumentException e) {
			System.out.println(tempStationName + " Not a valid station");
			getAndVerifyBadgeId();
		} catch (IllegalStateException e) {
			System.out.println(tempStationName + " Not a valid station");
			getAndVerifyBadgeId();
		} catch (NullPointerException e) {
			System.out.println("Station cannot be null");
			getAndVerifyBadgeId();
		}

	}
}
